package org.c41.graphics.swing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

import org.c41.graphics.swing.JC41Table.Row;
import org.c41.util.Arrays;
import org.c41.util.Check;

public class JC41Table extends JBasicTable {

	private C41DefaultTableModel model;
	
	public JC41Table(String[] columnName){
		Check.notNull(columnName);
		
		this.model=new C41DefaultTableModel(Arrays.copy(columnName));
		table.setModel(model);
	}
	
	public void insertRow(String... values){
		model.inner_insert(values);
		table.updateUI();
	}
	
	public void insertRow(int index, String...values){
		model.inner_insert(index,values);
		table.updateUI();
	}
	
	public void removeRow(int index){
		model.inner_remove(index);
		table.updateUI();
	}
	
	public void updateRow(int index, String... values){
		model.inner_update(index, values);
		table.updateUI();
	}
	
	public void setValue(int row, int column, String value){
		model.setValueAt(value, row, column);
		table.updateUI();
	}
	
	public String getValueAt(int row, int column){
		return model.getValueAt(row, column);
	}
	
	public Row getRow(int row){
		return model.inner_getRow(row);
	}
	
	public void sort(Comparator<Row> comp){
		model.inner_sort(comp);
		table.updateUI();
	}
	
	public static class Row {

		private String[] columns;
		
		Row(int length){
			this.columns = new String[length];
		}
		
		Row(String[] s){
			this.columns=s;
		}
		
		void set(int index, String value){
			this.columns[index]=value;
		}
		
		public String get(int index){
			return columns[index];
		}
		
		public int compareTo(Row row, int index){
			return this.get(index).compareTo(row.get(index));
		}
		
	}
	
}

class C41DefaultTableModel implements TableModel{

	private String[] columns;
	private ArrayList<Row> rows = new ArrayList<>();
	
	C41DefaultTableModel(String[] columns){
		this.columns=columns;
	}

	void inner_sort(Comparator<Row> comp) {
		Collections.sort(rows,comp);
	}

	Row inner_getRow(int row) {
		return rows.get(row);
	}

	void inner_update(int index, String[] values) {
		String[] row = new String[columns.length];
		int i=0;
		for(;i<values.length;i++){
			row[i]=values[i];
		}
		for(;i<columns.length;i++){
			row[i]=null;
		}
		rows.set(index,new Row(row));
	}

	void inner_remove(int index) {
		rows.remove(index);
	}

	void inner_insert(int index, String[] values) {
		String[] row = new String[columns.length];
		int i=0;
		for(;i<values.length;i++){
			row[i]=values[i];
		}
		for(;i<columns.length;i++){
			row[i]=null;
		}
		rows.add(index, new Row(row));
	}

	int inner_insert(String[] values) {
		String[] row = new String[columns.length];
		int i=0;
		for(;i<values.length;i++){
			row[i]=values[i];
		}
		for(;i<columns.length;i++){
			row[i]=null;
		}
		rows.add(new Row(row));
		return getRowCount()-1;
	}

	@Override
	public void addTableModelListener(TableModelListener l) {}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		return String.class;
	}

	@Override
	public int getColumnCount() {
		return this.columns.length;
	}

	@Override
	public String getColumnName(int columnIndex) {
		return this.columns[columnIndex];
	}

	@Override
	public int getRowCount() {
		return this.rows.size();
	}

	@Override
	public String getValueAt(int rowIndex, int columnIndex) {
		Row row = this.rows.get(rowIndex);
		return row.get(columnIndex);
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return false;
	}

	@Override
	public void removeTableModelListener(TableModelListener l) {}
	
	@Override
	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		this.rows.get(rowIndex).set(columnIndex,(String) aValue);
	}
	
}